# 导入相关的库
import tkinter as tk
import tkinter.messagebox as tkm
import numpy as np
from operator import eq


class Game_Moudle():
    def __init__(self, N: int, square_size: int, max_depth: int):  # square_size给定一个棋子的大小
        self.chessboard = tk.Tk()  # 创建一个基本的窗口或应用程序
        self.chessboard.title('博弈论实验七:五子棋人机对战小游戏')  # 设置窗口的标题
        screenwidth = self.chessboard.winfo_screenwidth()  # 返回当前计算机屏幕的像素宽度，即可见屏幕的宽度，不包括任务栏或其他任何边框
        screenheight = self.chessboard.winfo_screenheight()  # 返回当前计算机屏幕的像素高度，即可见屏幕的宽度，不包括任务栏或其他任何边框
        alignstr = '%dx%d+%d+%d' % (
            (N + 1) * square_size, (N + 1) * square_size, (screenwidth - (N + 1) * square_size) / 2,
            (screenheight - (N + 5) * square_size) / 2)
        self.chessboard.geometry(alignstr)  # 设置窗口的参数 宽度x高度+水平偏移量+垂直偏移量
        self.N = N
        self.total_num = 0
        self.square_size = square_size
        self.max_depth = max_depth
        self.user = False  # True：当前落子的是玩家
        self.ai_first = False
        self.waiting = True  # 当前实例是否等待用户操作
        self.end = False  # 当前游戏是否结束
        # 添加一个画布
        self.canvas = tk.Canvas(self.chessboard, width=(N + 1) * square_size, height=(N + 1) * square_size,
                                bg="#F6E6B6")
        self.chess = np.zeros((11, 11), dtype=int)  # 棋盘
        self.cur_choice_pos_x = 0
        self.cur_choice_pos_y = 0
        self.life2max = [[0, 0, 1, 1, 0, 0],
                         [0, 1, 0, 1, 0],
                         [0, 1, 0, 0, 1, 0]]
        self.life2min = [[0, 0, 2, 2, 0, 0],
                         [0, 2, 0, 2, 0],
                         [0, 2, 0, 0, 2, 0]]
        self.sleep2max = [[2, 1, 1, 0, 0, 0], [0, 0, 0, 1, 1, 2],
                          [2, 1, 0, 1, 0, 0], [0, 0, 1, 0, 1, 2],
                          [2, 1, 0, 0, 1, 0], [0, 1, 0, 0, 1, 2],
                          [0, 1, 0, 0, 0, 1, 0]]
        self.sleep2min = [[1, 2, 2, 0, 0, 0], [0, 0, 0, 2, 2, 1],
                          [1, 2, 0, 2, 0, 0], [0, 0, 2, 0, 2, 1],
                          [1, 2, 0, 0, 2, 0], [0, 2, 0, 0, 2, 1],
                          [0, 2, 0, 0, 0, 2, 0]]
        self.live3max = [[0, 0, 1, 1, 1, 0], [0, 1, 1, 1, 0, 0],
                         [0, 1, 1, 0, 1, 0], [0, 1, 0, 1, 1, 0]]
        self.live3min = [[0, 0, 2, 2, 2, 0], [0, 2, 2, 2, 0, 0],
                         [0, 2, 2, 0, 2, 0], [0, 2, 0, 2, 2, 0]]
        self.sleep3max = [[2, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 2],
                          [2, 1, 1, 0, 1, 0], [0, 1, 0, 1, 1, 2],
                          [2, 1, 0, 1, 1, 0], [0, 1, 1, 0, 1, 2],
                          [0, 1, 1, 0, 0, 1, 0], [0, 1, 0, 0, 1, 1, 0],
                          [0, 1, 0, 1, 0, 1, 0], [2, 0, 1, 1, 1, 0, 2]
                          ]
        self.sleep3min = [[1, 2, 2, 2, 0, 0], [0, 0, 2, 2, 2, 1],
                          [1, 2, 2, 0, 2, 0], [0, 2, 0, 2, 2, 1],
                          [1, 2, 0, 2, 2, 0], [0, 2, 2, 0, 2, 1],
                          [0, 2, 2, 0, 0, 2, 0], [0, 2, 0, 0, 2, 2, 0],
                          [0, 2, 0, 2, 0, 2, 0], [1, 0, 2, 2, 2, 0, 1]]
        self.live4max = [[0, 1, 1, 1, 1, 0]]
        self.live4min = [[0, 2, 2, 2, 2, 0]]
        self.rush4max = [[2, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 2],
                         [0, 1, 1, 1, 0, 1, 0], [0, 1, 0, 1, 1, 1, 0],
                         [0, 1, 1, 0, 1, 1, 0]]
        self.rush4min = [[1, 2, 2, 2, 2, 0], [0, 2, 2, 2, 2, 1],
                         [0, 2, 2, 2, 0, 2, 0], [0, 2, 0, 2, 2, 2, 0],
                         [0, 2, 2, 0, 2, 2, 0]]
        self.connect5 = [[1, 1, 1, 1, 1, ], [2, 2, 2, 2, 2]]
        # 画线格
        for i in range(0, N + 1):
            self.canvas.create_line(square_size, i * square_size, N * square_size, i * square_size, fill="#CFAA75")
            self.canvas.create_line(i * square_size, square_size, i * square_size, N * square_size, fill="#CFAA75")
        # 在画布上绘制棋盘上的五个星点
        self.star_points_x = [2, 2, 5, 8, 8]
        self.star_points_y = [2, 8, 5, 2, 8]
        for i in range(5):  # 使用create_oval()方法绘制椭圆形
            self.canvas.create_oval(square_size * (1 + self.star_points_x[i]) - (self.square_size // 10),
                                    square_size * (1 + self.star_points_y[i]) - (self.square_size // 10),
                                    square_size * (1 + self.star_points_x[i]) + (self.square_size // 10),
                                    square_size * (1 + self.star_points_y[i]) + (self.square_size // 10),
                                    fill="#C0A379", outline="#E6CD9C")
            # (x_0, y_0, x_1, y_1)为输入参数,(x_0, y_0)矩阵区域左上角坐标,(x_1,y_1)矩阵区域右下角坐标
        # 选中一格时的边框
        self.left_frame = self.canvas.create_line(0, 0, 0, 0, fill="white", dash=(4, 4))
        self.up_frame = self.canvas.create_line(0, 0, 0, 0, fill="white", dash=(4, 4))
        self.right_frame = self.canvas.create_line(0, 0, 0, 0, fill="white", dash=(4, 4))
        self.down_frame = self.canvas.create_line(0, 0, 0, 0, fill="white", dash=(4, 4))
        self.canvas.pack()  # 对画布进行打包，以便在界面上显示出来
        self.ai_first = tkm.askokcancel('', 'AI先手？')  # 创建一个对话框，询问先手方
        if self.ai_first:
            __, _ = self.ai_drop(5, 5, 'black')
            score = self.evaluate()
            print(score)
        self.canvas.bind("<Button-1>", self.click)  # 绑定点击鼠标左键为空操作
        self.canvas.bind("<Motion>", self.move)  # 绑定鼠标移动为空操作

    # 从画布坐标中得到网格坐标
    def get_idx(self, x: int, y: int):
        lower_x = x // self.square_size
        lower_y = y // self.square_size
        if x - (lower_x * self.square_size) <= (self.square_size // 2):
            pos_x = lower_x
        else:
            pos_x = lower_x + 1
        if y - (lower_y * self.square_size) <= (self.square_size // 2):
            pos_y = lower_y
        else:
            pos_y = lower_y + 1
        return pos_x, pos_y
    
    # 展示选中框
    def show_choice(self, x: int, y: int):
        pos_x, pos_y = self.get_idx(x, y)
        if pos_x != self.cur_choice_pos_x or pos_y != self.cur_choice_pos_y:  # 有变动才触发更新
            self.cur_choice_pos_x = pos_x
            self.cur_choice_pos_y = pos_y
            if self.cur_choice_pos_x in range(1, self.N + 1) and self.cur_choice_pos_y in range(1, self.N + 1):
                self.canvas.coords(self.left_frame,
                                   self.square_size * self.cur_choice_pos_x - (self.square_size // 3),
                                   self.square_size * self.cur_choice_pos_y - (self.square_size // 3),
                                   self.square_size * self.cur_choice_pos_x - (self.square_size // 3),
                                   self.square_size * self.cur_choice_pos_y + (self.square_size // 3))
                self.canvas.coords(self.up_frame,
                                   self.square_size * self.cur_choice_pos_x - (self.square_size // 3),
                                   self.square_size * self.cur_choice_pos_y - (self.square_size // 3),
                                   self.square_size * self.cur_choice_pos_x + (self.square_size // 3),
                                   self.square_size * self.cur_choice_pos_y - (self.square_size // 3))
                self.canvas.coords(self.right_frame,
                                   self.square_size * self.cur_choice_pos_x + (self.square_size // 3),
                                   self.square_size * self.cur_choice_pos_y - (self.square_size // 3),
                                   self.square_size * self.cur_choice_pos_x + (self.square_size // 3),
                                   self.square_size * self.cur_choice_pos_y + (self.square_size // 3))
                self.canvas.coords(self.down_frame,
                                   self.square_size * self.cur_choice_pos_x - (self.square_size // 3),
                                   self.square_size * self.cur_choice_pos_y + (self.square_size // 3),
                                   self.square_size * self.cur_choice_pos_x + (self.square_size // 3),
                                   self.square_size * self.cur_choice_pos_y + (self.square_size // 3))
            else:
                self.reset_frame()

    # 当选择时，鼠标移动
    def move(self, event):
        self.show_choice(event.x, event.y)
    
    # 重置选中框
    def reset_frame(self):
        self.canvas.coords(self.left_frame, 0, 0, 0, 0)
        self.canvas.coords(self.up_frame, 0, 0, 0, 0)
        self.canvas.coords(self.right_frame, 0, 0, 0, 0)
        self.canvas.coords(self.down_frame, 0, 0, 0, 0)

    # 用于处理鼠标左键点击事件
    def click(self, event):
        x, y = self.get_idx(event.x, event.y)  # 获取点击事件发生时鼠标的坐标位置
        x -= 1
        y -= 1
        if ~self.end:
            self.waiting = True  # 设置为等待状态
            self.user_drop(x, y)  # 落子

    # 画棋子
    def draw(self, x: int, y: int, color: str):  # 在
        self.canvas.create_oval(self.square_size * (1 + x) - (self.square_size // 3),
                                self.square_size * (1 + y) - (self.square_size // 3),
                                self.square_size * (1 + x) + (self.square_size // 3),
                                self.square_size * (1 + y) + (self.square_size // 3),
                                fill=color, outline=color)

    # ai落子
    def ai_drop(self, x, y, color):
        self.canvas.unbind("<Button-1>")  # 关闭点击操作
        self.canvas.unbind("<Motion>")
        if self.total_num == 0:
            temp_x = x
            temp_y = y
        else:
            temp_x, temp_y = self.ai(x, y)
        self.draw(temp_x, temp_y, color)  # AI落子
        self.chess[temp_y][temp_x] = 1 if color == 'black' else 2  # 标记为AI的子
        self.total_num += 1  # 棋子总数累加
        self.canvas.bind("<Button-1>", self.click)  # 恢复点击操作
        self.canvas.bind("<Motion>", self.move)
        state = self.check(temp_x, temp_y)  # 检查是否游戏结束
        if state:  # 如果是,游戏结束
            self.finish()
        return temp_x, temp_y

    # 玩家落子
    def user_drop(self, x: int, y: int):
        if self.ai_first:  # ai先手，黑棋
            if self.chess[y][x] == 0:
                self.user = True  # 标识当前落子的是玩家
                self.draw(x, y, 'white')  # 因为ai先手为黑子,玩家此时为白子
                self.chess[y][x] = 2  # 将棋盘对应位置记录为白子(1:黑子, 2:白子, 0:空)
                self.total_num += 1  # 棋子总数累加
                self.canvas.update()  # 更新画布
                state = self.check(x, y)  # 检查是否有一方获胜
                if state:
                    self.finish()  # 结束
                self.waiting = False  # 结束等待状态
            # ai行动
            if ~self.waiting and ~self.end:  # 当玩家成功下子之后，ai才行动
                self.user = False  # 标识当前落子的为ai
                self.ai_drop(x, y, 'black')  # ai落子
                score = self.evaluate()  # 计算得失
                print(score)  # 输出得分
        else:  # ai后手，白棋
            if self.chess[y][x] == 0:
                self.user = True  # 当前落子的是玩家
                self.draw(x, y, 'black')  # 因为ai后手为白子,玩家此时为黑子
                self.chess[y][x] = 1  # 将棋盘对应位置记录为黑子
                self.total_num += 1  # 棋子总数累加
                self.canvas.update()  # 更新画布
                state = self.check(x, y)  # 检查是否有一方获胜
                if state:
                    self.finish()  # 结束
                self.waiting = False  # 结束等待状态
            if ~self.waiting and ~self.end:  # 玩家成功下子之后，ai行动
                self.user = False  # 标识为当前落子的为ai
                self.ai_drop(x, y, 'white')  # ai落子
                score = self.evaluate()  # 计算得失
                print(score)  # 输出得失

    # 检查当前落的这个棋子能不能构成5连
    def check(self, x: int, y: int) -> bool:
        return self.row_check(x, y) or self.col_check(x, y) or self.dia_check(x, y)  # 分别按照行/列/对角线判断输赢

    # 检查行
    def row_check(self, x, y):
        dx = [-1, 1]  # 分别向左向右查看
        num = 1
        for d in dx:
            test_x = x + d
            while 0 <= test_x <= 10 and self.chess[y][test_x] == self.chess[y][x]:
                num += 1
                test_x += d
            if num >= 5:
                return True
        return False

    def col_check(self, x, y):
        dy = [-1, 1]
        num = 1
        for d in dy:
            test_y = y + d
            while 0 <= test_y <= 10 and self.chess[test_y][x] == self.chess[y][x]:
                num += 1
                test_y += d
            if num >= 5:
                return True
        return False

    def dia_check(self, x, y):
        dx = [-1, 1, 1, -1]
        dy = [-1, 1, -1, 1]
        num = 1
        for i in range(len(dx)):
            if i == 2:
                num = 1
            test_x = x + dx[i]
            test_y = y + dy[i]
            while 0 <= test_x <= 10 and 0 <= test_y <= 10 and self.chess[test_y][test_x] == self.chess[y][x]:
                num += 1
                test_x += dx[i]
                test_y += dy[i]
            if num >= 5:
                return True
        return False

    # 结束游戏
    def finish(self):
        self.end = True  # 游戏结束的标志
        self.canvas.unbind("<Motion>") # 关闭显示操作
        self.canvas.unbind("<Button-1>")  # 关闭点击操作
        tkm.showinfo('Game over', '{:s} win.'.format('User' if self.user else 'AI'))  # 判断谁赢了

    # ============================  AI  ============================#
    # ai选取一个点的坐标
    def ai(self, x, y):
        val, my_x, my_y = self.minmax(x, y, self.max_depth, -INF, INF, self.ai_first)
        print('AI choose [{:2d}, {:2d}] to drop, The score is: '.format(my_x, my_y), end="")
        self.canvas.update()
        return my_x, my_y
        # minmax搜索，带剪枝

    def minmax(self, x, y, depth, a, b, max_player):
        # x 和 y 是当前要落子的位置坐标
        # depth 是搜索的深度
        # a 和 b 是 alpha-beta 剪枝中的参数
        # max_player 则表示当前玩家是最大化玩家还是最小化玩家   player=0：max，player=1：min
        if depth == 0:
            return self.evaluate(), x, y  # 如果搜索的深度为 0，则直接返回当前局面的评估值和要落子的位置
        if max_player:  # max玩家
            # 简述一下思路:如果当前玩家是最大化玩家，则在可行的下棋位置中选择一个最优的位置，使得当前局面的评估值最大化。
            # 在循环中，通过遍历所有可行的下棋位置，并模拟在该位置落子的情况，递归调用 minmax 方法来评估这个子状态。
            # 然后根据 alpha-beta 剪枝的原理，更新 alpha 和 beta 值，以减少搜索的次数。最后返回最优解的评估值和对应的下棋位置。
            maxval = -INF
            best_x = 0
            best_y = 0
            for point in self.valid_positions(x, y):  # 遍历能够落子的位置列表（遍历子状态）
                next_x = point[1][0]
                next_y = point[1][1]
                self.chess[next_y][next_x] = 1 if max_player else 2  # 把尝试走的这一步写在地图上
                val, _, _ = self.minmax(next_x, next_y, depth - 1, a, b, False)
                self.chess[next_y][next_x] = 0  # 把操作还原
                if val > maxval:
                    best_x = next_x
                    best_y = next_y
                maxval = max(val, maxval)
                a = max(val, a)
                if b <= a:
                    break
            return maxval, best_x, best_y
        else:  # min玩家
            # 如果当前玩家是最小化玩家，则在可行的下棋位置中选择一个最优的位置，使得当前局面的评估值最小化。
            # 其实现原理和最大化玩家的代码类似，只是在更新最优解的过程中使用了 min 函数，以及在更新 alpha-beta 剪枝参数时取 min 而不是 max。
            minval = +INF
            best_x = 5
            best_y = 5
            for point in self.valid_positions(x, y):  # 遍历能够落子的位置列表（遍历子状态）
                next_x = point[1][0]
                next_y = point[1][1]
                self.chess[next_y][next_x] = 1 if max_player else 2  # 把尝试走的这一步写在地图上
                val, _, _ = self.minmax(next_x, next_y, depth - 1, a, b, True)
                self.chess[next_y][next_x] = 0  # 把操作还原
                if val < minval:
                    best_x = next_x
                    best_y = next_y
                minval = min(val, minval)
                b = min(val, b)
                if b <= a:
                    break
            return minval, best_x, best_y

    def valid_positions(self, x, y):
        # 它接受当前要落子的位置坐标 (x, y)，然后遍历整个棋盘，找到所有未落子的位置，并计算每个位置到目标位置 (x, y) 的曼哈顿距离 d。
        # 最后，将每个位置及其对应的距离添加到 check_list 列表中。
        check_list = []
        for next_x in range(self.N):
            for next_y in range(self.N):  # 遍历整个棋盘
                if self.chess[next_y][next_x] == 0:  # 允许落子的位置
                    d = abs(next_x - x) + abs(next_y - y)  # 计算曼哈顿距离
                    check_list.append([d, [next_x, next_y]])
        return sorted(check_list)  # 通过d(曼哈顿距离)来排序

    # 遍历棋盘上的每个位置，检查横向、纵向和对角线方向上可能的获胜组合
    def evaluate(self):
        total = 0   # 存储累积的评估值
        for x in range(self.N):
            for y in range(self.N): # 遍历整个棋盘
                if self.chess[y][x] != 0:  # 没有棋子的格子可以不看
                    dir_offset = [1, 0]  # 横线
                    line = self.getline(x, y, dir_offset)
                    total += self.analysisline(line)
                    dir_offset = [0, 1]  # 竖线
                    line = self.getline(x, y, dir_offset)
                    total += self.analysisline(line)
                    dir_offset = [1, 1]  # 左上右下线
                    line = self.getline(x, y, dir_offset)
                    total += self.analysisline(line)
                    dir_offset = [1, -1]  # 右上左下线
                    line = self.getline(x, y, dir_offset)
                    total += self.analysisline(line)
        return total

    # 返回x,y确定的棋子为中心的线，drt_offset确定移动方式（两个数，表示右/下方向），opponent是对方的代号
    def getline(self, x, y, dir_offset):
        line = [0 for i in range(9)]
        temp_x = x + (-5 * dir_offset[0])
        temp_y = y + (-5 * dir_offset[1])
        for i in range(9):
            temp_x += dir_offset[0]
            temp_y += dir_offset[1]
            if 0 <= temp_x <= 10 and 0 <= temp_y <= 10:
                line[i] = self.chess[temp_y][temp_x]
            else:
                line[i] = -1
        return line

    # 评估这条线上的得分
    def analysisline(self, line) -> int:
        total = 0
        total += self.judge_length5(line)
        total += self.judge_length6(line)
        total += self.judge_length7(line)
        return total

    # 判断2连子的情况
    def judge2(self, line) -> int:
        total = 0
        # 判断活2
        for i in range(4):
            window = line[i:i + 6]
            for sample in self.life2max:
                if eq(window, sample):
                    total += bonus['live2']
            for sample in self.life2min:
                if eq(window, sample):
                    total -= bonus['live2']
        for i in range(5):
            window = line[i:i + 5]
            if eq(window, self.life2max[1]):
                total += bonus['live2']
            if eq(window, self.life2min[1]):
                total -= bonus['live2']
        for i in range(4):
            window = line[i:i + 6]
            for sample in self.sleep2max:
                if eq(window, sample):
                    total += bonus['sleep2']
            for sample in self.sleep2min:
                if eq(window, sample):
                    total -= bonus['sleep2']
        for i in range(3):
            window = line[i:i + 7]
            if eq(window, self.sleep2max[1]):
                total += bonus['sleep2']
            if eq(window, self.sleep2min[1]):
                total -= bonus['sleep2']
        return total

    # 判断3连子的情况
    def judge3(self, line) -> int:
        total = 0
        for i in range(4):
            window = line[i:i + 6]
            for sample in self.live3max:
                if eq(window, sample):
                    total += bonus['live3']
            for sample in self.live3min:
                if eq(window, sample):
                    total -= bonus['live3']
        # 眠3
        for i in range(4):
            window = line[i:i + 6]
            for sample in self.sleep3max[0:6]:
                if eq(window, sample):
                    total += bonus['sleep3']
            for sample in self.sleep3min[0:6]:
                if eq(window, sample):
                    total -= bonus['sleep3']
        for i in range(3):
            window = line[i:i + 7]
            for sample in self.sleep3max[6:10]:
                if eq(window, sample):
                    total += bonus['sleep3']
            for sample in self.sleep3min[6:10]:
                if eq(window, sample):
                    total -= bonus['sleep3']
        return total

    # 判断4连子的情况
    def judge4(self, line) -> int:
        total = 0
        # 活4
        for i in range(4):
            window = line[i:i + 6]
            for sample in self.live4max:
                if eq(window, sample):
                    total += bonus['live4']
            for sample in self.live4min:
                if eq(window, sample):
                    total -= bonus['live4']
        # 冲4
        for i in range(4):
            window = line[i:i + 6]
            for sample in self.rush4max[0:2]:
                if eq(window, sample):
                    total += bonus['rush4']
            for sample in self.rush4min[0:2]:
                if eq(window, sample):
                    total -= bonus['rush4']
        for i in range(3):
            window = line[i:i + 7]
            for sample in self.sleep3max[2:5]:
                if eq(window, sample):
                    total += bonus['rush4']
            for sample in self.sleep3min[2:5]:
                if eq(window, sample):
                    total -= bonus['rush4']
        return total

    # 判断连5，无方向
    def judge5(self, line) -> int:
        total = 0
        for i in range(5):
            window = line[i:i + 5]  # 取出5个
            if eq(window, self.connect5[0]):
                total += bonus['connect5']
            if eq(window, self.connect5[1]):
                total -= bonus['connect5']
        return total

    # 判断长度为5的
    def judge_length5(self, line):
        total = 0
        for i in range(5):
            window = line[i:i + 5]
            if eq(window, self.life2max[1]):
                total += bonus['live2']
            if eq(window, self.life2min[1]):
                total -= bonus['live2']
            if eq(window, self.connect5[0]):
                total += bonus['connect5']
            if eq(window, self.connect5[1]):
                total -= bonus['connect5']
        return total

    # 判断长度为6
    def judge_length6(self, line):
        total = 0
        for i in range(4):
            window = line[i:i + 6]
            for sample in self.life2max:
                if eq(window, sample):
                    total += bonus['live2']
            for sample in self.life2min:
                if eq(window, sample):
                    total -= bonus['live2']
            for sample in self.sleep2max:
                if eq(window, sample):
                    total += bonus['sleep2']
            for sample in self.sleep2min:
                if eq(window, sample):
                    total -= bonus['sleep2']
            for sample in self.live3max:
                if eq(window, sample):
                    total += bonus['live3']
            for sample in self.live3min:
                if eq(window, sample):
                    total -= bonus['live3']
            for sample in self.sleep3max[0:6]:
                if eq(window, sample):
                    total += bonus['sleep3']
            for sample in self.sleep3min[0:6]:
                if eq(window, sample):
                    total -= bonus['sleep3']
            for sample in self.live4max:
                if eq(window, sample):
                    total += bonus['live4']
            for sample in self.live4min:
                if eq(window, sample):
                    total -= bonus['live4']
            for sample in self.rush4max[0:2]:
                if eq(window, sample):
                    total += bonus['rush4']
            for sample in self.rush4min[0:2]:
                if eq(window, sample):
                    total -= bonus['rush4']
        return total

    # 判断长度为7的
    def judge_length7(self, line):
        total = 0
        for i in range(3):
            window = line[i:i + 7]
            if eq(window, self.sleep2max[1]):
                total += bonus['sleep2']
            if eq(window, self.sleep2min[1]):
                total -= bonus['sleep2']
            for sample in self.sleep3max[6:10]:
                if eq(window, sample):
                    total += bonus['sleep3']
            for sample in self.sleep3min[6:10]:
                if eq(window, sample):
                    total -= bonus['sleep3']
            for sample in self.sleep3max[2:5]:
                if eq(window, sample):
                    total += bonus['rush4']
            for sample in self.sleep3min[2:5]:
                if eq(window, sample):
                    total -= bonus['rush4']
        return total


# 不同情况初始化得分
bonus = {'connect5': 100_000,
         'live4': 5000,
         'rush4': 1000,
         'live3': 400,
         'sleep3': 100,
         'live2': 10,
         'sleep2': 1}
INF = 1_000_000_000_000
game = Game_Moudle(11, 50, 2)
game.chessboard.mainloop()
